package net.nio;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @author 王霄
 * @date 2021/8/27 20:26
 */
public class NioServer {
    public static void main(String[] args) throws Exception {
        //创建serverSocketChannel -> serverSocket
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //创建一个Selector对象
        Selector selector = Selector.open();
        //绑定一个端口
        serverSocketChannel.bind(new InetSocketAddress(6666));
        //设置为非阻塞
        serverSocketChannel.configureBlocking(false);
        //将serverSocketChannel注册到selector,关系事件 OP_ACCEPT
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        //循环等待客户端连接
        while (true) {
            //阻塞一秒
            if (selector.select(1000) == 0) {
                System.out.println("服务器等待了一秒,无连接");
                continue;
            }
            //获取相关的selectionKey集合
            //如果返回的大于0,说明已经获取到关注的事件
            //selector.selectedKeys() 获取关注事件的集合
            //通过selectionKeys 反向获取通道
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                //有新的客户端连接
                if (selectionKey.isAcceptable()) {
                    //给该客户端生成一个socketChannel
                    //通过该客户端生成一个socketChannel
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    //设置为非阻塞
                    socketChannel.configureBlocking(false);
                    //将socketChannel注册到selector,同时给socketChannel关联一个buffer
                    socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
                }

                //发生读取事件
                if (selectionKey.isReadable()) {
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    ByteBuffer buffer = (ByteBuffer) selectionKey.attachment();
                    socketChannel.read(buffer);
                    System.out.println("收到客户端数据：" + new String(buffer.array()));
                }

                iterator.remove();
            }
        }
    }
}
